#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <signal.h>
#include <sys/stat.h>
#include "time.h"

#include "core.h"
#include "click.h" 
#include "user_operation.h"
#include "guess_number.h"

static char getch(void);
static void make_rank(int grace, struct account_data* core_head, char* core_g_name);
static void run_crazy_click(struct account_data* core_head, char* core_g_name);
static int nonblocking_input(void);

/*
 *@brief        游玩疯狂输入游戏
 */
void crazy_click(struct account_data* core_head, char* core_current_user_name)
{
	if (!core_head && !core_current_user_name) {
        DEBUG("PARAM ERROR!\n");
        return;
    }
    
	run_crazy_click(core_head, core_current_user_name);
}

void run_crazy_click(struct account_data* core_head, char* core_g_name)
{	
    if (!core_head && !core_g_name) {
        DEBUG("PARAM ERROR!\n");
        return;
    }
    
    int count, ret;
    char judge, quit;
    int grace = 0;
    time_t start_time, end_time;

    printf("\n\n\n\n\n\n\n\n\n\t\t-------------crazy click-------------");
    printf("\n\t\t游戏规则：在十秒内尽可能多的点击除开q的字符按键，\n\t\t按q为退出游戏，排行榜按点击次数从高到低排名");
    printf("\n\t\tWhen you are ready, press 1 to start\n\t\t\t\t");
    
    judge = 0;
   	while (judge != 1) {
   		judge = judge_number(4);
   			
   		if (judge != 1) {
   			printf("\n\t\tplease input 1:");
		}
	}
    
    /*倒计时*/
    system("clear");
    if (judge == 1) {
        for (count = 3; count >0; count--) {
    	    printf("\n\t\t\t\t\t%d ...\n", count);
    	    if (count == 1) {
    			sleep(1);
    			printf("\n\t\t\t\t\tGO!\n");
	    	}
    	    sleep(1);
		}
	
        /*开始游戏*/
		system("stty -echo");  
		system("stty -icanon");
		
		start_time = time(NULL);
    	end_time = start_time;
    	
    	while ((end_time - start_time) <= 10) {
    		if (nonblocking_input()) {
    			quit = getch();
	    		grace++;
	    		ret = 1;
			}
	    	
	    	if (quit == 'q') {
	    		grace = grace - 1;
				break;
	    	}
	    	end_time = time(NULL);
		}
	    
		system("stty icanon");
		system("stty echo");
		
		if (ret == 1) {
			grace--;
		}
		
        LOG("用户%s游玩疯狂点击游戏", core_g_name);
		printf("\n\t\tCongratulations, finish the game,your score is 10 seconds, click %d\n", grace);
		printf("\t\tPress 1 to view the rankings.\n\t\t");

        LOG("用户%s查看排行榜", core_g_name);
		
        judge = 0;
   		while (judge != 1) {
   			judge = judge_number(4);
   			
   			if (judge != 1) {
   				printf("\n\t\tplease input 1:");
			}
		}
		
		if (judge == 1) {
	    	system("clear");
	    	make_rank(grace , core_head, core_g_name);
		}
    }
}

/*
 *@brief        更新成绩以及输出排行榜
 */
void make_rank(int grace, struct account_data* core_head, char* core_g_name)
{
    if (!core_head && !core_g_name) {
        DEBUG("PARAM ERROR!\n");
        return;
    }
    
    int ret;
    struct account_data *scan_list, *previous_list, *HEAD,
	*need_change, *previous_need_change, *behind_list, *now_list;
    int rank = 1;
    
    /*将scan_list指向链表中的最后一个节点*/
    scan_list = core_head->next;
    while (scan_list != NULL) {
		if (strcmp(scan_list->name, core_g_name) == 0) {
	    	break;
		}
        scan_list = scan_list->next;
    }
    
    /*比较原成绩与当前成绩的大小，若当前成绩更高，则覆盖原成绩*/
    if (grace > scan_list->grace) {
		scan_list->grace = grace;
    }
    now_list = scan_list;
    
    HEAD = core_head->next;
	need_change = core_head->next;
	while (strcmp(need_change->name, core_g_name) != 0) {
		if (now_list->grace > need_change->grace) {
			ret = 1;
			break;
		}
		else {
			ret = 0;
		}
		
		need_change = need_change->next;
	}
	/*链表排序*/
	scan_list = core_head->next;
    if (now_list->next == NULL && ret == 1) {
    	if (strcmp(need_change->name, HEAD->name) == 0) {
    		while (strcmp(scan_list->name, now_list->name) != 0) {
    			previous_list = scan_list;
    			scan_list =  scan_list->next;
			}
			previous_list->next = NULL;
			core_head->next = now_list;
			now_list->next = need_change;
		}
		else {
			while (strcmp(scan_list->name, need_change->name) != 0) {
				previous_need_change = scan_list;
				scan_list = scan_list->next;
			}
			while (strcmp(scan_list->name, now_list->name) != 0) {
				previous_list = scan_list;
				scan_list = scan_list->next;
			}
			previous_list->next = NULL;
			previous_need_change->next = now_list;
			now_list->next = need_change;
		}
	}
	else if (now_list != NULL && ret == 1) {
		if (now_list->grace > HEAD->grace) {
			while (strcmp(scan_list->name, now_list->name) != 0) {
				previous_list = scan_list;
				scan_list = scan_list->next;
			}
			behind_list = now_list->next;
			
			core_head->next = now_list;
			now_list->next = need_change;
			previous_list->next = behind_list; 
		}
		else {
			while (strcmp(scan_list->name, now_list->name) != 0) {
				previous_list = scan_list;
				scan_list = scan_list->next;
			}
			behind_list = now_list->next;
			scan_list = core_head->next;
			while (strcmp(scan_list->name, need_change->name) != 0) {
				previous_need_change = scan_list;
				scan_list = scan_list->next;
			}
			previous_list->next = behind_list;
			previous_need_change->next = now_list;
			now_list->next = need_change;
		}
	}
	
    scan_list = core_head->next;
    while (scan_list != NULL) {
		printf("\t\tThe NO.%d name is %s,his best achievement is:%d\n",
		rank, scan_list->name, scan_list->grace);
		scan_list = scan_list->next;
		rank++;
    }
    sleep(2);
}

/*
 *@brief        实现windows中getch()的效果
 *@param        c:输入的字符
 *@return       输入的字符
 */
char getch(void)
{
    char c;
    c = getchar();
    
    return c;
}
/*
 *@brief        无阻塞输入
 *return        成功返回1，失败返回0
 */
int nonblocking_input(void)
{
	fd_set set;
	struct timeval time;
	int ret;

	time.tv_sec = 0;
	time.tv_usec = 0;
	FD_ZERO(&set);
	FD_SET(STDIN_FILENO, &set);
	
	if (select(STDIN_FILENO + 1, &set, NULL, NULL, &time) != -1) {
		if (FD_ISSET(STDIN_FILENO, &set)) {
			ret = 1;
		} 
		else
			ret = 0;
	}
	else
		ret = EOF;

	FD_CLR(STDIN_FILENO, &set);

	return ret;
}
